home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / Graphic Elements 3 / GEBreakout / Breakout.c < prev   
C/C++ Source or Header  |  1995-08-28  |  12KB  |  573 lines

  1. /*
  2.     Breakout.c
  3.     
  4.     Breakout demo for Graphic Elements library
  5.     
  6.     3/7/94
  7.     
  8.     Al Evans
  9.     
  10.     Note: This is a fairly generic application shell.
  11.     The interesting parts are all in BGame.h and .c
  12.     
  13.     Sound added 8/22/95
  14. */
  15.  
  16. //Load precompiled symbol table if under MPW
  17. #ifdef applec
  18. #ifndef PRELOAD
  19. #pragma load "::ToolKit.precompile"
  20. #define PRELOAD
  21. #endif
  22. #else
  23. #include <QDOffscreen.h>
  24. #endif
  25.  
  26. #include <Timer.h>
  27. #include <GestaltEqu.h>
  28. #include "GUtilities.h"
  29. #include "GraphElements.h"
  30. #include "BGame.h"
  31.  
  32. // Adding sounds
  33. #include "GESound.h"
  34.  
  35. //define HISTOGRAM to collect times history
  36. #undef HISTOGRAM
  37.  
  38. #ifdef HISTOGRAM
  39. #include "StdIO.h"
  40. #endif
  41.  
  42.  
  43. //Menu Commands
  44.  
  45. #define    rMenuBar                128        /* application's menu bar */
  46.  
  47. #define    mApple                    128        /* Apple menu */
  48. #define    iAbout                    1
  49.  
  50. #define    mFile                    129        /* File menu */
  51. #define iNewGame                1
  52. #define    iQuit                    2
  53.  
  54. #define    mEdit                    130        /* Edit menu */
  55. #define    iUndo                    1
  56. #define    iCut                    3
  57. #define    iCopy                    4
  58. #define    iPaste                    5
  59. #define    iClear                    6
  60.  
  61. #define mSpecial                131
  62. #define iSingleFrame            1
  63.  
  64. #define    rAboutDialog            228        
  65.  
  66.  
  67. //Number of master pointer blocks needed
  68.  
  69. #define masterBlocksNeeded 10
  70.  
  71. //Globals
  72.  
  73. Boolean        gFinished;
  74. WindowPtr    gAnimWindow;
  75. Boolean        gSingleFrame = false;
  76. Boolean        gDoOne = false;
  77.  
  78. //Performance measurement
  79.  
  80. #define thirtySeconds 30L * 1000 * 1000        //µsec for timers -- never time out
  81.  
  82. TMTask    gTTimeTask, gATimeTask;
  83. unsigned long gTotalTime = 0, gAnimTime = 0;
  84.  
  85. #ifdef HISTOGRAM
  86. long    animTimes[100];
  87. long    mainTimes[100];
  88. #endif
  89.  
  90. //Forward declarations
  91.  
  92. #ifdef applec
  93. extern void _DataInit();    //reference so that we can unload it
  94. #endif
  95.  
  96. Boolean Initialize( void );
  97. void Shutdown(void);
  98. void EventLoop( void );
  99.  
  100. main()
  101. {
  102. #ifdef applec
  103.     UnloadSeg((Ptr) _DataInit);
  104. #endif
  105.     
  106.     MaxApplZone();
  107.     if ( Initialize() )
  108.         EventLoop();
  109.     Shutdown();
  110. }
  111.  
  112.  
  113. //Initialization
  114.  
  115. Boolean AdequateSystem(void)
  116. {
  117.     OSErr        err;
  118.     long        response;
  119.     Boolean        ok;
  120.     
  121.     //We need 68020 or better
  122.     err = Gestalt(gestaltProcessorType, &response);
  123.     ok = (!err) & (response >= gestalt68020);
  124.     
  125.     //We need System 7 or later
  126.     err = Gestalt(gestaltSystemVersion, &response);
  127.     ok = (!err) & (((response & 0xFFFF) / 256) >= 7);
  128.     
  129.     //We need color QD & offscreen GWorlds
  130.     err = Gestalt(gestaltQuickdrawVersion, &response);
  131.     ok = ok & (!err) & (response >= gestalt32BitQD);
  132.     err = Gestalt(gestaltQuickdrawFeatures, &response);
  133.     ok = ok & (!err) & (response >= 3);         //hasColor & deep GWorlds
  134.     
  135.     return ok;
  136.     
  137. }
  138.  
  139. //Make window centered on main graphic device
  140. WindowPtr MakeWindow(short wHSize, short wVSize)
  141. {
  142.     GDHandle    mainDevice;
  143.     Rect        devRect;
  144.     short        hOffst, vOffst;
  145.     Rect        windRect;
  146.     
  147.     mainDevice = GetMainDevice();
  148.     devRect = (**mainDevice).gdRect;
  149.     hOffst = (devRect.right - devRect.left - wHSize) / 2;
  150.     if (hOffst < 0) hOffst = 0;
  151.     vOffst = (devRect.bottom - devRect.top - wVSize) / 2;
  152.     if (vOffst < 0 ) vOffst = 0;
  153.     windRect.left = hOffst;
  154.     windRect.right = hOffst + wHSize;
  155.     windRect.top = vOffst;
  156.     windRect.bottom = vOffst + wVSize; 
  157.     
  158.     return NewCWindow(nil, &windRect, "\pGEBreakout", false, documentProc,
  159.                         (WindowPtr) -1L, false, 0L);
  160. }
  161.  
  162. void InitPerformanceTiming(void)
  163. {
  164.     //Init Timers
  165.     gTTimeTask.tmAddr = nil;
  166.     gTTimeTask.tmWakeUp = 0;
  167.     gTTimeTask.tmReserved = 0;
  168.     
  169.     gATimeTask.tmAddr = nil;
  170.     gATimeTask.tmWakeUp = 0;
  171.     gATimeTask.tmReserved = 0;
  172.     
  173. }
  174.  
  175. Boolean Initialize(void)
  176. {
  177.     Rect        animRect;
  178.     GEWorldPtr    animWorld;
  179.     GESoundPtr    animWorldSounds;
  180.     
  181.     pascal void MaintainSounds(GEWorldPtr world, Ptr soundRec);
  182.  
  183. #ifdef HISTOGRAM
  184.     short    count;
  185. #endif
  186.     
  187.     gFinished = false;
  188.     
  189.     InitSystem(masterBlocksNeeded);
  190.     
  191.     
  192.     if (!AdequateSystem()) {
  193.         TellUser("\pSorry, more powerful system required", 0);
  194.         return false;
  195.     }
  196.     if (!LoadMenus(rMenuBar)) {
  197.         TellUser("\pCould not load menus", 0);
  198.         return false;
  199.     }
  200.     
  201.     //Create window and install animation
  202.     if (gAnimWindow = MakeWindow(gWindWidth, gWindHeight)){
  203.         animWorldSounds = GEInitSounds(4);
  204.         if (animWorldSounds == nil) {
  205.             TellUser("\pCould not initialize sounds", 0);
  206.             return false;
  207.         }
  208.         animRect.left = 0;
  209.         animRect.right = gWindWidth;
  210.         animRect.top = 0;
  211.         animRect.bottom = gWindHeight;
  212.         if (animWorld = NewGEWorld((GrafPtr) gAnimWindow, &animRect, scaleOneToOne, nil))
  213.             SetWRefCon(gAnimWindow, (long) animWorld);
  214.         else {
  215.             TellUser("\pCould not install animation in window", 0);
  216.             return false;
  217.         }
  218.         // Set for automatic sound maintenance
  219.         SetPostProcFunc(animWorld, MaintainSounds, (Ptr) animWorldSounds);
  220.     }
  221.     else {
  222.         TellUser("\pCould not create window", 0);
  223.         return false;
  224.     }
  225.     
  226.     InitPerformanceTiming();
  227.     qd.randSeed = TickCount();
  228.     
  229.     //Load game graphics
  230.     
  231.     if (!LoadBreakoutGame(animWorld)) {
  232.         TellUser("\pCould not load game graphics", 0);
  233.         return false;
  234.     }
  235.         
  236. #ifdef HISTOGRAM
  237.     for (count = 0; count < 100; count++) {
  238.         animTimes[count] = 0;
  239.         mainTimes[count] = 0;
  240.     }
  241. #endif
  242.  
  243.     
  244.     //Turn animation on and show window
  245.     ShowWindow(gAnimWindow);
  246.     ActivateWorld((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  247.     return true;
  248.     
  249. }
  250.  
  251. #ifdef HISTOGRAM
  252. void DumpHistograms(void)
  253. {
  254.     short    count;
  255.     FILE*    dump;
  256.     
  257.     dump = fopen("HistoDump", "w");
  258.     for (count = 0; count < 100; count++) 
  259.         fprintf(dump, "%d\t%d\t%d\n", count, mainTimes[count], animTimes[count]);
  260.     fflush(dump);
  261.     fclose(dump);
  262. }
  263. #endif
  264.  
  265. void Shutdown(void)
  266. {
  267.     GEWorldPtr world = (GEWorldPtr) GetWRefCon(gAnimWindow);
  268.     
  269.     //Release system resources
  270.     
  271. #ifdef HISTOGRAM
  272.     DumpHistograms();
  273. #endif
  274.  
  275.     if (world) {
  276.         if (world->userData)
  277.             GEDisposeSounds((GESoundPtr) world->userData);
  278.         DisposeGEWorld(world);
  279.     }
  280.     
  281.     ExitToShell();
  282. }
  283.  
  284.  
  285. #ifdef HISTOGRAM
  286. void DoHistogram(void)
  287. {
  288.     if ((gTotalTime - gAnimTime) < 100)
  289.         mainTimes[(gTotalTime - gAnimTime)]++;
  290.     else
  291.         mainTimes[99]++;
  292.     if (gAnimTime < 100)
  293.         animTimes[gAnimTime]++;
  294.     else
  295.         animTimes[99]++;
  296. }
  297. #endif
  298.  
  299. pascal Boolean AboutFilter(DialogPtr dialog, EventRecord *event, short *item)
  300. {
  301. #pragma unused (dialog)
  302.     DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), false);
  303.     if ((event->what == mouseDown) || (event->what == keyDown)) {
  304.         *item = ok;
  305.         return true;
  306.     }
  307.     else return false;
  308. }
  309.  
  310. void DoAboutBox(void)
  311. {
  312.     DialogPtr    aboutDialog;
  313.     short        itemHit;
  314.     
  315.     aboutDialog = GetNewDialog(rAboutDialog, nil, (WindowPtr) -1L);
  316.     ModalDialog(AboutFilter, &itemHit);
  317.     DisposDialog(aboutDialog);
  318. }
  319.  
  320.  
  321. pascal void MaintainSounds(GEWorldPtr world, Ptr soundRec)
  322. {
  323.     GESoundMaintenance((GESoundPtr) soundRec);
  324. }
  325.  
  326. //Event Handling
  327.  
  328. void EventLoop( void )
  329. {
  330.     Boolean        gotEvent;
  331.     EventRecord    event;
  332.     
  333.     void DoEvent (EventRecord *event);
  334.     void AdjustCursor( void);
  335.  
  336.     do {
  337.     
  338. #ifdef HISTOGRAM
  339.         InsTime( (QElemPtr) &gTTimeTask);
  340.         InsTime( (QElemPtr) &gATimeTask);
  341.         PrimeTime( (QElemPtr) &gTTimeTask, -thirtySeconds);
  342. #endif
  343.  
  344.         if (!gSingleFrame || gDoOne) {
  345.         
  346. #ifdef HISTOGRAM
  347.             PrimeTime( (QElemPtr) &gATimeTask, -thirtySeconds);
  348. #endif
  349.  
  350.             DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), false);
  351.             
  352. #ifdef HISTOGRAM
  353.             RmvTime( (QElemPtr) &gATimeTask);
  354.             gAnimTime = (thirtySeconds + gATimeTask.tmCount) / 1000;
  355. #endif
  356.  
  357.             gDoOne = false;
  358.         }
  359.         AdjustCursor();
  360.         if (gotEvent = WaitNextEvent(everyEvent, &event, 0L, nil)) 
  361.             DoEvent(&event);
  362.             
  363. #ifdef HISTOGRAM
  364.         RmvTime( (QElemPtr) &gTTimeTask);
  365.         gTotalTime = (thirtySeconds + gTTimeTask.tmCount) / 1000; //milliseconds
  366.         DoHistogram();
  367. #endif
  368.  
  369.     } while (!gFinished);
  370. }
  371.  
  372. void DoEvent (EventRecord *event)
  373. {
  374.     short        part;
  375.     WindowPtr    window;
  376.     char        key;
  377.     
  378.     //Prototypes
  379.     void AdjustMenus( void );
  380.     void DoMenuCommand(long menuResult);
  381.     void DoActivate(WindowPtr window, Boolean becomingActive);
  382.     void DoUpdate(WindowPtr window);
  383.     
  384.     switch ( event->what ) {
  385.         case mouseDown:
  386.             part = FindWindow(event->where, &window);
  387.             switch ( part ) {
  388.                 case inMenuBar:
  389.                     AdjustMenus();
  390.                     DoMenuCommand(MenuSelect(event->where));
  391.                     break;
  392.                 case inSysWindow:
  393.                     SystemClick(event, window);
  394.                     break;
  395.                 case inContent:
  396.                     if ( window != FrontWindow() ) 
  397.                         SelectWindow(window);
  398.                     if (MouseDownInSensor((GEWorldPtr) GetWRefCon(gAnimWindow), event->where))
  399.                         ;;
  400.                     break;
  401.                 case inDrag:
  402.                     DragWindow(window, event->where, &qd.screenBits.bounds);
  403.                     break;
  404.             }
  405.             break;
  406.         case keyDown:
  407.             key = event->message & charCodeMask;
  408.             if ( event->modifiers & cmdKey ) {
  409.                 AdjustMenus();
  410.                 DoMenuCommand(MenuKey(key));
  411.             }
  412.             else {
  413.                 switch (key) {
  414.                     case 'U':
  415.                     case 'u':
  416.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 0, -50);
  417.                         break;
  418.                     case 'D':
  419.                     case 'd':
  420.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 0, 50);
  421.                         break;
  422.                     case 'R':
  423.                     case 'r':
  424.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 50, 0);
  425.                         break;
  426.                     case 'L':
  427.                     case 'l':
  428.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), -50, 0);
  429.                         break;
  430.                 }
  431.             }
  432.             gDoOne = true;
  433.             break;
  434.         case activateEvt:
  435.             DoActivate((WindowPtr) event->message, (event->modifiers & activeFlag) != 0);
  436.             break;
  437.         case updateEvt:
  438.             DoUpdate((WindowPtr) event->message);
  439.             break;
  440.         case osEvt:
  441.             switch ((event->message >> 24) & 0x0FF) {
  442.                 case suspendResumeMessage:
  443.                     gInBackground = (event->message & resumeFlag) == 0;
  444.                     DoActivate(FrontWindow(), !gInBackground);
  445.                     break;
  446.             }
  447.             break;
  448.         }
  449. }
  450.  
  451. void DoActivate(WindowPtr window, Boolean becomingActive)
  452. {
  453. #pragma unused (window)
  454.     //Start and stop animation here
  455.     ActivateWorld((GEWorldPtr) GetWRefCon(gAnimWindow), becomingActive);
  456. }
  457.  
  458.  
  459. void DoUpdate(WindowPtr window)
  460. {
  461.     Rect geRect;
  462.     GEWorldPtr geWorld;
  463.  
  464.     if (window == gAnimWindow)
  465.     {
  466.         SetPort( (GrafPtr) window );
  467.         //Protect GEWorld rect before updating window, since we will draw it
  468.         geWorld = (GEWorldPtr) GetWRefCon(gAnimWindow);
  469.         geRect = geWorld->animationRect;
  470.         RectOffset(&geRect, geWorld->worldFocus.h, geWorld->worldFocus.v);
  471.         ValidRect(&geRect);
  472.         
  473.         BeginUpdate(window);
  474.             FillRgn(((GrafPtr) window)->visRgn, (ConstPatternParam) &qd.gray);
  475.         EndUpdate(window);
  476.         
  477.         DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  478.     }
  479. }
  480.  
  481. void AdjustMenus( void )
  482. {
  483.     WindowPtr    window;
  484.     MenuHandle    menu;
  485.     
  486.     window = FrontWindow();
  487.     
  488.     menu = GetMHandle(mFile);
  489.     EnableItem(menu, iNewGame);
  490.     EnableItem(menu, iQuit);
  491.  
  492.     menu = GetMHandle(mEdit);
  493.     if (window = gAnimWindow) {
  494.         DisableItem(menu, iUndo);
  495.         DisableItem(menu, iCut);
  496.         DisableItem(menu, iCopy);
  497.         DisableItem(menu, iClear);
  498.         DisableItem(menu, iPaste);
  499.     }
  500.     else {
  501.         EnableItem(menu, iUndo);
  502.         EnableItem(menu, iCut);
  503.         EnableItem(menu, iCopy);
  504.         EnableItem(menu, iClear);
  505.         EnableItem(menu, iPaste);
  506.     }
  507.     menu = GetMHandle(mSpecial);
  508.     //Set up special items!
  509.     CheckItem(menu, iSingleFrame, gSingleFrame);
  510. }
  511.  
  512. void DoMenuCommand(long menuResult)
  513. {
  514.     short        menuID;
  515.     short        menuItem;
  516.     Str255        daName;
  517.     short        daRefNum;
  518.  
  519.     menuID = HiWord(menuResult);
  520.     menuItem = LoWord(menuResult);
  521.     switch ( menuID ) {
  522.         case mApple:
  523.             switch ( menuItem ) {
  524.                 case iAbout:
  525.                     DoAboutBox();
  526.                     break;
  527.                 default:            /* all other items in this menu are DAs */
  528.                     GetItem(GetMHandle(mApple), menuItem, daName);
  529.                     daRefNum = OpenDeskAcc(daName);
  530.                     break;
  531.             }
  532.             break;
  533.         case mFile:
  534.             switch(menuItem) {
  535.                 case iNewGame:
  536.                     NewBreakoutGame((GEWorldPtr) GetWRefCon(gAnimWindow));
  537.                     ActivateWorld((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  538.                     ShowWindow(gAnimWindow);
  539.                     break;
  540.                 case iQuit:
  541.                     gFinished = true;
  542.             }
  543.             break;
  544.         case mEdit:
  545.             (void) SystemEdit(menuItem-1);
  546.             break;
  547.         case mSpecial:
  548.             //Add special items
  549.             switch ( menuItem ) {
  550.                 case iSingleFrame:
  551.                     gSingleFrame = !gSingleFrame;
  552.                     break;
  553.             }
  554.             break;
  555.     }
  556.     HiliteMenu(0);
  557. }
  558.  
  559. //Utility routines
  560.  
  561.  
  562. void AdjustCursor( void )
  563. {
  564.     WindowPtr    window;
  565.     
  566.     window = FrontWindow();
  567.     
  568.     if ( (window == gAnimWindow) && (!gInBackground) ) {
  569.         SetCursor(&qd.arrow);
  570.     }
  571. }
  572.  
  573.